import json
import uuid
from typing import Union
from rest_framework import serializers
from apps.utils.helper.red_package_helper import RedPackageHelper
from apps.actions.models import ActionTab, RedEnvelop, RedEnvelopReceive
from apps.user.models import User
from apps.utils.helper.image_helper import ImageHelper
from apps.utils.helper.xunfei_image_helper import check_action_image


class ActionSerializer(serializers.ModelSerializer):

    class Meta:
        model = ActionTab
        fields = '__all__'


class RedEnvelopInfoSerializer(serializers.ModelSerializer):

    actions_lists = serializers.SerializerMethodField(read_only=True, help_text='红包关联的动作信息')
    receive_envelops = serializers.SerializerMethodField(read_only=True, help_text='红包关联已经领取的红包记录')
    send_user = serializers.SerializerMethodField(read_only=True, help_text='红包发送的用户')
    amount = serializers.SerializerMethodField(help_text='红包发送的总金额')
    total_receive_amount_of_cent = serializers.SerializerMethodField(help_text='已经领取的红包金额')

    class Meta:
        model = RedEnvelop
        fields = ('title', 'created_time', 'count', 'total_receive_count',
                  'total_receive_amount_of_cent', 'send_status',
                  'actions_lists', 'receive_envelops', 'send_user', 'amount')

    def get_amount(self, obj):
        return float(obj.amount) * 0.01

    def get_total_receive_amount_of_cent(self, obj):
        return float(obj.total_receive_amount_of_cent) * 0.01

    def get_send_user(self, obj):
        user = User.objects.get(pk=obj.send_user_id)
        if not user:
            return {}
        return {'send_user_nickname': user.nickname or '', 'send_user_avatar': str(user.avatar_url) or ''}

    def get_actions_lists(self, obj) -> list:
        actions_list = json.loads(obj.action_id_list)
        if not actions_list:
            return []
        actions_objs = ActionTab.objects.filter(id__in=actions_list)
        ser = ActionSerializer(actions_objs, many=True)
        return ser.data

    def get_receive_envelops(self, obj) -> list:
        receive_envelops = RedEnvelopReceive.objects.filter(red_envelop_uuid=obj.id)
        if receive_envelops.count() == 0:
            return []

        result = []
        users = User.objects.filter(id__in=receive_envelops.values_list('receive_user_uuid', flat=True)).all()
        users_mapping = {
            user.id: {
                'nickname': user.nickname or '',
                'avatar_url': str(user.avatar_url) or ''
            }
            for user in users
        }
        actions_list = ActionTab.objects.filter(id__in=receive_envelops.values_list('receive_action_uuid', flat=True)).all()
        actions_mappings = {
            action.id: {
                'description': action.description or '',
                'image_url': str(action.image_url) or '',
            }
            for action in actions_list
        }
        for receive_envelop in receive_envelops:
            data = {
                'nickname': users_mapping[receive_envelop.receive_user_uuid].get('nickname', ''),
                'avatar_url': users_mapping[receive_envelop.receive_user_uuid].get('avatar_url', ''),
                'receive_amount_of_cent': receive_envelop.receive_amount_of_cent,
                'description': actions_mappings[receive_envelop.receive_action_uuid].get('description', ''),
                'image_url': actions_mappings[receive_envelop.receive_action_uuid].get('image_url', ''),
            }
            result.append(data)
        return result


class RedEnvelopSerializer(serializers.ModelSerializer):
    class Meta:
        model = RedEnvelop
        fields = ('id', 'title', 'amount', 'total_receive_amount_of_cent', 'created_time', 'send_status')


class RedEnvelopReceiveSerializer(serializers.ModelSerializer):

    title = serializers.SerializerMethodField(read_only=True, help_text='对应action的description')

    class Meta:
        model = RedEnvelopReceive
        fields = ('title', 'red_envelop_uuid', 'receive_amount_of_cent', 'receive_timestamp')

    def get_title(self, obj) -> str:
        red_action = ActionTab.objects.filter(id=obj.receive_action_uuid)
        if red_action.exists():
            return red_action.first().description
        return ''


class ActionCreateSerializer(serializers.Serializer):

    amount = serializers.DecimalField(max_digits=10, decimal_places=2, write_only=True, help_text='支付金额')
    count = serializers.IntegerField(write_only=True, help_text='发送红包的数量')
    action_ids = serializers.ListField(write_only=True, help_text='对应动作的ids')


class RedEnvelopCreateSerializer(serializers.Serializer):
    amount = serializers.DecimalField(max_digits=10, decimal_places=2, write_only=True, help_text='支付金额')
    count = serializers.IntegerField(write_only=True, help_text='发送红包的数量')
    action_ids = serializers.ListField(write_only=True, help_text='对应动作的ids')

    def create(self, validated_data) -> Union[serializers.ValidationError, None, RedEnvelop]:
        current_user = getattr(self.context['request'], 'current_user', None)
        # 处理支付手续费
        send_amount_of_cent = int(float(validated_data.get('amount')) * (1 - 0.02) * 100)
        allocate_amount_lists = RedPackageHelper.allocate_red_package_money(send_amount_of_cent, validated_data.get('count'))

        # 假设这是微信支付的交易流水号
        wx_out_trade_no = uuid.uuid4().hex

        red_envelop_qs = RedEnvelop.objects.filter(out_trade_no=wx_out_trade_no)
        if red_envelop_qs.exists():
            raise serializers.ValidationError(f'红包任务已经存在了! id={red_envelop_qs.first().id}')

        action_lists = ActionTab.objects.filter(id__in=validated_data.get('action_ids')).all()
        action_description_str = '|'.join([o.description for o in action_lists])

        red_envelop = RedEnvelop(
            out_trade_no=wx_out_trade_no,
            send_user_id=current_user.id,
            title=action_description_str,
            amount=send_amount_of_cent,
            count=validated_data.get('count'),
            action_id_list=json.dumps(validated_data.get('action_ids')),
            pre_allocated_amount_of_cent_list=json.dumps(allocate_amount_lists),
        )
        red_envelop.save()
        return red_envelop


class RedEnvelopChanllengeSerializer(serializers.Serializer):

    red_package_uuid = serializers.UUIDField(write_only=True, help_text='红包挑战的uuid')
    chanllenge_action_uuid = serializers.UUIDField(write_only=True, help_text='对应挑战动作的uuid')
    chanllenge_action_image = serializers.ImageField(write_only=True, help_text='上传挑战动作的图片')

    def create(self, validated_data):
        user = getattr(self.context['request'], 'current_user', None)
        save_target = ImageHelper.save_chanllenge_image(validated_data.get('chanllenge_action_image'), validated_data.get('chanllenge_action_uuid'), user.wei_chat_open_id)

        action_tab_obj = ActionTab.objects.filter(id=validated_data.get('chanllenge_action_uuid'))
        if not action_tab_obj.exists():
            raise serializers.ValidationError('动作不存在')

        action_description = action_tab_obj.first().description or ''
        # 检查动作是否符合挑战动作的描述
        if not check_action_image(save_target, action_description):
            return False
        return True
